package org.xhy.sniffer.plugin;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.net.URL;

/**
 * @description: 该类用于找到 dist 文件夹（可能包含 Agent JAR 文件），即通过寻找代理程序的类路径，推断其所在位置。
 * dist：插件的目录
 * @gitee: https://gitee.com/XhyQAQ
 * @copyright: B站: https://space.bilibili.com/152686439
 * @Author: Xhy
 * @CreateTime: 2024-07-11 20:10
 */
@Slf4j // 使用 Lombok 自动生成日志功能
public class AgentPackagePath {

    // 保存找到的 Agent 包的路径
    private static File AGENT_PACKAGE_PATH;

    /**
     * 获取 Agent 包的路径
     * 如果路径还未初始化（即第一次调用），通过 findPath 方法寻找路径
     *
     * @return File 返回找到的包的路径
     */
    public static File getPath() {
        if (AGENT_PACKAGE_PATH == null) {
            // 如果路径还未初始化，调用 findPath() 方法查找
            AGENT_PACKAGE_PATH = findPath();
        }
        return AGENT_PACKAGE_PATH;
    }

    /**
     * 查找 Agent 包路径的核心方法
     * 通过定位当前类的字节码文件位置，推断出代理 JAR 文件的存放目录
     *
     * @return File 返回 JAR 文件所在的父目录
     */
    private static File findPath() {
        // 获取当前类的完整路径，比如 "org/xhy/sniffer/plugin/AgentPackagePath.class"
        String classResourcePath = AgentPackagePath.class.getName().replaceAll("\\.", "/") + ".class";

        // 获取该类资源的 URL，通常指向该类文件在文件系统或 JAR 文件中的位置
        // file:/Users/xhy/IdeaProjects/xhy-skywalking/dist/agent-1.0-SNAPSHOT-jar-with-dependencies.jar!/org/xhy/sniffer/plugin/AgentPackagePath.class
        URL resource = ClassLoader.getSystemClassLoader().getResource(classResourcePath);

        // 如果找到了资源路径，进一步处理
        if (resource != null) {
            String urlString = resource.toString(); // 将 URL 转为字符串

            log.info("The beacon class location is {}.", urlString); // 打印日志，记录类的位置

            // 检查资源是否位于 JAR 文件中（通过检查 URL 中是否包含 '!'）
            boolean isInJar = urlString.indexOf('!') > -1;

            if (isInJar) {
                // 如果类在 JAR 文件中，提取 JAR 文件的路径
                // 比如提取路径：/Users/xhy/IdeaProjects/xhy-skywalking/dist/agent-1.0-SNAPSHOT-jar-with-dependencies.jar
                urlString = StringUtils.substringBetween(urlString, "file:", "!");

                File agentJarFile = null;
                try {
                    // 尝试将 URL 字符串转换为 File 对象
                    agentJarFile = new File(urlString);
                } catch (Exception e) {
                    // 如果转换失败，记录错误日志，并显示无法定位代理 JAR 文件
                    log.error("Can not locate agent jar file by url:{}", urlString, e);
                }

                // 如果找到了 JAR 文件，返回它的父目录，即 JAR 文件所在的目录
                if (agentJarFile.exists()) {
                    return agentJarFile.getParentFile();
                }
            }
        }

        // 如果没有找到 JAR 文件，记录错误日志，并抛出异常
        log.error("Can not locate agent jar file.");
        throw new RuntimeException("Can not locate agent jar file.");
    }
}
